########################################################一.Makefile的规则########################################################################
#	给目标文件(.obj或.o)打个包,这个包在Windows下叫Library File其实就是.lib文件,在UNIX下是Archive File也就是.a文件

#	当出现链接错误时(Linker Error),其实就是链接器未能找到函数的实现(也就是函数对应的Object File找不到)


#	一.Makefile的规则。
#       	 target ... :prerequisites ...
#        	command
#       	 ...
#       	 ...
#
#       	 target也就是一个目标文件,可以是Object File,也可以是可执行文件,还可以是一个标签(Label),对于标签这种特性,在后续
#	的"伪目标"章节会有叙述。
#        prerequisites就是要生成那个target所需的文件或是目标。
#        command也就是make需要执行的命令。(任意的Shell命令)
#
#        这是一个文件的依赖关系,就是说,target这一个或多个目标文件依赖于prerequisites中的文件,其生成规则定义在command中。
#	说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会执行。美其名曰:Makefile
#	的规则,是Makefile中最核心的内容。


########################################################二.一个示例##############################################################################

edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o     #反斜杠(\)是换行符的意思
	cc -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o 
#	定义了如何生成目标文件的操作系统命令,一定要以Tab按键作为开头
#	make并不管命令是怎样工作的,他只管执行所定义的命令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比
#	targets文件的日期要更新
#	或者target不存在的话,那么make就会执行后续定义的命令
main.o : main.c defs.h
	cc -c main.c

kbd.o : kbd.c defs.h command.h
	cc -c kbd.c

command.o : command.c defs.h command.h
	cc -c command.c

display.o : display.c defs.h buffer.h
	cc -c display.c

insert.o : insert.c defs.h buffer.h
	cc -c insert.c

search.o : search.c defs.h buffer.h
	cc -c search.c

files.o : files.c defs.h buffer.h command.h
	cc -c files.c

utils.o : utils.c defs.h
	cc -c utils.c

#	clean不是一个文件,他只不过是一个动作名字,有点像C语言中的label一样,其冒号后面什么也没有,那么make就不会自动去找文件的依赖性,也就不会自动执行其##	     后面所定义的命令。

#	要执行其后面的命令,就要在make命令后明显指出这个label的名字。这其实很有用,可以在makefile中定义不用编译的 或是和编译无关的命令,比如程序的打包,##	     程序的备份等等!
clean : 
	rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o
 



########################################################三.make是如何工作的########################################################################

<<<<<<< HEAD
#	默认情况下,也就是我们只输入make命令。那么make会在当前目录下找到名字叫Makefile或makefile的文件
#	如果找到,它会找文件中的第一个目标文件(target),上例中,他会找到edit这个文件,并把这个文件作为最终的目标文件
#	如果edit文件不存在,或是edit所依赖的后面的.o文件修改时间要比edit这个文件新,那么他就会执行后面所定义的命令来生成edit这个文件
#	如果edit所依赖的.o文件也存在,那么make会在当前文件
=======

#	make会在当前目录下找名字叫"Makefile"或"makefile"的文件
#	如果找到了,它会找文件中的第一个目标文件(target)，在上面的例子中会找到"edit"这个文件,并把这个文件作为最终的目标文件
#	在寻找依赖的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,
#	make根本不理。也就是make只管文件的依赖性。就是说如果我找到了依赖关系之后,冒号后面的文件还是不存在,那么对不起,我make就不工作了
#	但是像clean这种是个例外,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令就不会被自动执行,但我们可以显示要make执行。即
#	——————"make clean"

#	于是在我们编程中,如果这个工程已经被编译过了,当我们修改了其中一个源文件,比如file.c,那么根据依赖性,目标file.o会被重编译(就是执行
#	这个依赖关系后面的命令),于是file.o的文件也就是最新得啦!然后就是file.o的文件修改时间要比edit更新,所以edit也会被重新链接(就是执行其后的命令)
#	其它也就类似

######################################################四.makefile或者Makefile中使用变量#######################################

#	在上面的示例中.o文件的字符串被重复了两次,如果我们的工程需要加入一个新的.o文件,那么我们需要在多个地方加。当然我们的
#	makefile不太复杂,所以在多个地方加.o不会太累,但如果makefile变得复杂,那么这样搞下去就会很复杂,会很累人的,而且还很容易
#	出错。所以为了makefile更易于维护,在makefile中我们可以使用变量。makefile的变量也就是一个字符串,理解成C语言中的宏更好


#	比如,我们声明一个变量,叫objects,OBJECTS,objs,OBJS,obj或是OBJ都可以,只要可以表示obj文件就可以了。那么我们的makefile就
#	可以这样定义了:
object = main.o kbd.o command.o display.o insert.o \
search.o files.o utils.o

#	于是我们就可以在makefile中以"$(objects)"的方式来使用这个变量了,于是这个改良版的makefile就变成下面这样了:

objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o

edit : $(objects)
	cc -o edit $(objects)    #注意这里是-o,而下面是-c
	
main.o : main.c defs.h
	cc -c main.c

kbd.o : kbd.c defs.h command.h
	cc -c kbd.c

command.o : command.c defs.h command.h
	cc -c command.c

display.o : display.c defs.h buffer.h
	cc -c display.c 

insert.o : insert.c defs.h buffer.h
	cc -c insert.c

search.o : search.c defs.h buffer.h
	cc -c search.c

files.o : files.c defs.h buffer.h command.h
	cc -c files.c

utils.o : utils.c defs.h
	cc -c utils.c

clean :
	rm edit $(objects)

#	于是如果有新的.o文件加入,我们只需简单地修改一下objects变量就可以了。

#################################################################五.让make自动推导######################################################

#	make很强大,
#	GNU 的 make 很强大，它可以自动推导文件以及文件依赖关系后面的命令，于是我们就没必
#	要去在每一个[.o]文件后都写上类似的命令，因为，我们的 make 会自动识别，并自己推导命令。 
 
#	只要 make 看到一个[.o]文件，它就会自动的把[.c]文件加在依赖关系中，如果 make
#	找到一个 whatever.o，那么 whatever.c，就会是 whatever.o 的依赖文件。并且 cc -c 
#	whatever.c 也会被推导出来，于是，我们的 makefile 再也不用写得这么复杂。我们的是新
#	的 makefile 又出炉了。 
 
 
第 11 页共 78 页 2005 年 10 月 14 日整理：祝冬华
跟我一起写 Makefile 作者：陈皓
objects = main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 
 
edit : $(objects) 
cc -o edit $(objects) 
 
main.o : defs.h 
kbd.o : defs.h command.h 
command.o : defs.h command.h 
display.o : defs.h buffer.h 
insert.o : defs.h buffer.h 
search.o : defs.h buffer.h 
files.o : defs.h buffer.h command.h 
utils.o : defs.h 
 
.PHONY : clean 
clean : 
rm edit $(objects) 
 
这种方法，也就是 make 的“隐晦规则”。上面文件内容中，“.PHONY”表示，clean
是个伪目标文件。
>>>>>>> c957d318dc377705c30a1cc2d698eea7e13a496f
